home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
System Booster
/
System Booster.iso
/
Archives
/
Timing
/
clocktool.lha
/
ClockTool
/
ClockTool.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-11-06
|
31KB
|
1,743 lines
#define VERSION "2.1 "
#define EARLIEST_LIB 37 /* 2.04 and above */
/* *INDENT-OFF* */
/**
* ClockTool.c
*
* Displays/adjusts/sets times of battery clock and/or system clock
* from one or the other.
*
* Options:
*
* -b ; battery clock
* -s ; system clock
* -d<str> ; set selected clock to str (dd-MMM-yy)
* -t<str> ; set selected clock to str (hh:mm[:ss])
* (use either or both d/t options)
* -annnn ; adjust selected clock time by -nnnn millisecs",
* +annnn ; adjust selected clock time by +nnnn millisecs",
* -l<file> ; log system time to <file> , reset clock from other
* (default LOG_CLOCKTOOL:)
* -L<file> ; log system time to <file> , Dont reset clock from other
* (default LOG_CLOCKTOOL:)
* -n<str> ; append the <str> to log file entry, e.g. "reboot"
*
* (see Usage () )
*
* Runs under AmigaDOS 2.04+, and only machines containing
* a battery clock.
*
*
*
***** Written by Gary Duncan
*
* 57 Melbourne Hill Rd
* Warrandyte
* Vic 3113
* Australia
*
* E-mail: gduncan@werple.net.au
*
*
***** Freely distributable for non-commercial purposes.
* Please keep this header intact.
*
*
* Compiles under SAS 6.2
*
* Formatted with 'indent -gnu' ; a big time-saving program.
*
* Functions:-
main
tv2dss
tv2str
dss2tv
dss2str
str2dss
Init_Timer
hexit
DeleteTimer
usage
scan_args
tv_diff
tv_diff_str
format_diff_str
set_system_time
get_system_time
get_battclock_time
set_battclock_time
tv_update
check4battclock
get_syncd_battclock_time
get_syncd_system_time
print_clock
display_clocks
adjust_clock
set_system_time_to_syncd_battclock
set_battclock_time_to_syncd_system_time
wait_for_timer
pause
Version Date Changes
~~~~~~~ ~~~~ ~~~~~~~
1.0 27Oct93 Original release
1.1 04Apr94 Changes :-
1) use __AMIGADATE__
2) added L option, reorganised logic.
3) added d,t options (set date/time).
4) corrected clocktool -b output for big difference
1.1a Comments added
2.0 18Apr95 Exit with good/bad (0/1) values
2.1 26Oct95 trivial changes to help
**/
/* *INDENT-ON* */
#include "ClockTool.h"
/*
* string for AmigaDOS Version Command
*/
char A_vers[] = "\0$VER: clocktool\t" VERSION __AMIGADATE__;
LIBRARY *UtilityBase = NULL;
LIBRARY *BattClockBase;
TIMEVAL tv_sysclock;
TIMEVAL tv_battclock;
TIMEVAL tv_tmp;
DATESTAMP dss_sysclock;
DATESTAMP dss_battclock;
DATETIME datetime;
char *date_ptr;
char *time_ptr;
LONG adjust;
LONG temp;
MSGPORT *TimeP = NULL;
TIMERREQUEST *Timermsg;
IOREQUEST *Timer = NULL;
BOOL a_flag = FALSE;
BOOL b_flag = FALSE;
BOOL d_flag = FALSE;
BOOL l_flag = FALSE;
BOOL L_flag = FALSE;
BOOL n_flag = FALSE;
BOOL s_flag = FALSE;
BOOL t_flag = FALSE;
char buf[80];
char *xstr = "";
int opt_count = 0;
char *logfile;
FILE *fp = NULL;
char log_buf[80];
/*
* used by date conversion functions
*/
DM days_month[] =
{
31, "Jan",
28, "Feb",
31, "Mar",
30, "Apr",
31, "May",
30, "Jun",
31, "Jul",
31, "Aug",
30, "Sep",
31, "Oct",
30, "Nov",
31, "Dec",
};
/*
*********************************************************************
*/
VOID
main (int argc, char **argv)
{
/*
* abort if no battclock and not AmigaDos 2.xx
*/
if (check4battclock () == FALSE)
{
hexit (1);
}
scan_args (argc, argv);
if (Init_Timer () == FALSE)
{
hexit (1);
}
/*
***** Mode (1) ? - just display both clocks ?
*/
if (opt_count == 0)
{
get_syncd_battclock_time (&tv_battclock);
get_system_time (&tv_sysclock);
display_clocks (&tv_battclock, &tv_sysclock);
hexit (0);
}
/*
***** Mode (2) - just a s or b option ?
*/
if (opt_count == 1)
{
/*
* just set one clock from the other
*/
if (s_flag == TRUE)
{
(void) set_system_time_to_syncd_battclock ();
print_old_new ("system", &tv_sysclock, &tv_battclock);
}
else
/* set battclock from system time */
{
(void) set_battclock_time_to_syncd_system_time ();
print_old_new ("battery", &tv_battclock, &tv_sysclock);
}
hexit (0);
}
/*
***** Mode (3) - set date/time from command line ?
*/
if ((d_flag == TRUE) || (t_flag == TRUE))
{
TIMEVAL t_val;
DateStamp (&datetime.dat_Stamp);
datetime.dat_Format = FORMAT_DOS;
datetime.dat_Flags = 0;
if (d_flag)
{
datetime.dat_StrDate = date_ptr;
datetime.dat_StrTime = NULL;
if (StrToDate (&datetime) == FALSE)
{
fprintf (stderr, "invalid date string\n");
hexit (1);
}
}
if (t_flag)
{
datetime.dat_StrTime = time_ptr;
datetime.dat_StrDate = NULL;
if (StrToDate (&datetime) == FALSE)
{
fprintf (stderr, "invalid time string\n");
hexit (1);
}
}
/*
* now change date/time of selected clock
*/
dss2tv (&datetime.dat_Stamp, &t_val);
b_flag ? set_battclock_time (&t_val) : set_system_time (&t_val);
/*
* now display both clocks
*/
get_syncd_battclock_time (&tv_battclock);
get_system_time (&tv_sysclock);
display_clocks (&tv_battclock, &tv_sysclock);
hexit (0);
}
/*
***** Mode (4) - adjust a clock (no logging) ?
*/
if ((a_flag == TRUE) && (opt_count == 2))
{
adjust_clock (adjust, &tv_tmp);
if (s_flag == TRUE)
{
print_old_new ("system", &tv_sysclock, &tv_tmp);
}
else
{
print_old_new ("battery", &tv_battclock, &tv_tmp);
}
hexit (0);
}
/*
***** Mode (5) - log selected clock time with reset ?
*/
if (l_flag == TRUE)
{
if (s_flag == TRUE)
{
temp = set_system_time_to_syncd_battclock ();
sprintf (log_buf, "\nS: %s %s",
tv2str (&tv_sysclock),
format_diff_str (temp, "(%s secs) "));
}
else if (b_flag == TRUE)
{
temp = set_battclock_time_to_syncd_system_time ();
sprintf (log_buf, "\nB: %s %s",
tv2str (&tv_battclock),
format_diff_str (temp, "(%s secs) "));
}
if (n_flag == TRUE)
{
strcat (log_buf, xstr);
}
printf ("%s\n", log_buf);
}
/*
***** Mode (6) - log selected clock time with NO reset ?
*/
if (L_flag == TRUE)
{
get_syncd_battclock_time (&tv_battclock);
get_system_time (&tv_sysclock);
temp = tv_diff (&tv_sysclock, &tv_battclock);
if (s_flag == TRUE)
{
sprintf (log_buf, "\nS: %s %s", tv2str (&tv_sysclock),
format_diff_str (temp, "(%s secs) "));
}
else if (b_flag == TRUE)
{
sprintf (log_buf, "\nB: %s %s", tv2str (&tv_battclock),
format_diff_str (temp, "(%s secs) "));
}
if (n_flag == TRUE)
{
strcat (log_buf, xstr);
}
#if 1
printf ("%s\n", log_buf);
#endif
}
/*
* now log message , maybe
*/
if (fp)
{
int rote;
int len = strlen (log_buf);
if ((rote = fwrite (log_buf, 1, len, fp)) != len)
{
fprintf (stderr, "fwrite error (wanted=%d),(actual=%d)\n",
len, rote);
hexit (99);
}
}
hexit (0);
}
/***************************************************************************
Function : tv2dss
Purpose: given a Timeval structure , returns Datestamp
Entry : ptr to Timeval
ptr to Datestamp
Returns :
****************************************************************************/
void
tv2dss (TIMEVAL * tv, DATESTAMP * dss)
{
long rem;
dss->ds_Days = tv->tv_secs / (24 * 60 * 60);
rem = tv->tv_secs % (24 * 60 * 60); /* secs in last day */
dss->ds_Minute = rem / 60;
rem = rem % 60; /* secs in last minute */
rem = (rem * 1000) + (tv->tv_micro / 1000); /* msecs in last minute */
dss->ds_Tick = rem / (1000 / TICKS_PER_SECOND); /* ticks in last minute */
}
/***************************************************************************
Function : tv2str
Purpose: given a Timeval structure , returns date string
Entry : ptr to Timeval
Returns :
****************************************************************************/
char *
tv2str (TIMEVAL * tv)
{
static char tbuf[40];
DATESTAMP dss;
tv2dss (tv, &dss);
dss2str (&dss, tbuf);
return tbuf;
}
/***************************************************************************
Function : dss2tv
Purpose: given a DateStamp structure , returns an updated TIMEVAL
Entry : ptr to DateStamp structure
Returns :
****************************************************************************/
void
dss2tv (DATESTAMP * t1, TIMEVAL * tv)
{
ULONG secs;
secs = t1->ds_Days * 24 * 60 * 60;
secs += t1->ds_Minute * 60;
secs += t1->ds_Tick / TICKS_PER_SECOND;
tv->tv_secs = secs;
tv->tv_micro = (t1->ds_Tick % TICKS_PER_SECOND) * (1000000 / TICKS_PER_SECOND);
}
/***************************************************************************
Function : dss2str
Purpose: generates a date string given a DateStamp
Entry : ptr to Datestamp
Returns : ptr to date string
****************************************************************************/
void
dss2str (DATESTAMP * dss, char *str)
{
static TIMEVAL tv;
struct tm Time;
int j;
long time, ago;
dss2tv (dss, &tv); /* date to secs/usecs since 01 Jan 78 */
time = tv.tv_secs;
Time.tm_sec = time % 60;
time /= 60;
Time.tm_min = time % 60;
time /= 60;
Time.tm_hour = time % 24;
time /= 24;
Time.tm_wday = time % 7;
Time.tm_year = 78 + (time / (4 * 365 + 1)) * 4;
time %= 4 * 365 + 1;
while (time)
{
ago = 365;
if ((Time.tm_year & 3) == 0) /* leap year */
ago++;
if (time < ago)
break;
time -= ago;
Time.tm_year++;
}
Time.tm_yday = ++time;
for (j = 0; j < 12; j++)
{
ago = days_month[j].days;
if (j == 1 && (Time.tm_year & 3) == 0) /* Feb , and leap year ? */
ago++;
if (time <= ago)
break;
time -= ago;
}
Time.tm_mon = j;
Time.tm_mday = time;
/* date format : 23-dec-88 22:33:01 */
sprintf (str, "%02d-%s-%2d %02d:%02d:%02d.%03d",
Time.tm_mday,
days_month[Time.tm_mon].months,
Time.tm_year,
Time.tm_hour,
Time.tm_min,
Time.tm_sec,
tv.tv_micro / 1000
);
}
/***************************************************************************
Function : str2dss
Purpose : converts a truncated Amiga date string to a Datestamp
e.g. "22-Dec-92 08:10:26" , no leading day
Entry :
Returns : TRUE if successful, FALSE otherwise
****************************************************************************/
BOOL
str2dss (char *str, DATESTAMP * ds)
{
/* 012345678901234567 */
/* 22-Dec-92 08:10:26 */
char *p = str;
ULONG dss_days;
int day, month, year, hour, min, sec, diy, j, k, rem;
p[2] = '\0';
p[6] = '\0';
p[9] = '\0';
p[12] = '\0';
p[15] = '\0';
day = atoi (&p[0]);
year = atoi (&p[7]) + 1900;
hour = atoi (&p[10]);
min = atoi (&p[13]);
sec = atoi (&p[16]);
/*
* compute days-in-year from month
* - may be incremented later if a leap year
*/
for (p = str + 3, j = 0, diy = 0;; ++j)
{
if (j == 12)
return FALSE;
if (strcmp (p, days_month[j].months) == 0)
{
month = j + 1;
break;
}
diy += days_month[j].days;
}
/*
* tricky bit ; adjust for leap years
*/
dss_days = diy + day - 1;
dss_days += 2 * 365; /* 1978, 1979 */
for (j = 1980, k = 0;;)
{
dss_days += 365;
if ((rem = (k++ % 4)) == 0)
dss_days += 1; /* leap year */
if (++j == year)
{
if (((rem = (k++ % 4)) == 0) && (month > 2))
{
dss_days += 1;
}
break;
}
}
ds->ds_Days = dss_days;
/*
* now fill in mins, ticks in min
*/
ds->ds_Minute = (60 * hour) + min;
ds->ds_Tick = sec * TICKS_PER_SECOND;
return TRUE;
}
/***************************************************************************
Function : Init_Timer
Purpose: Inits timer
Entry :
Returns :
****************************************************************************/
BOOL
Init_Timer (void)
{
int error;
TimeP = CreatePort (0, 0);
if (TimeP == NULL)
return FALSE;
Timermsg = (TIMERREQUEST *) CreateExtIO (TimeP, sizeof (TIMERREQUEST));
if (Timermsg == NULL)
return FALSE;
error = OpenDevice (TIMERNAME, UNIT_MICROHZ, (IOREQUEST *) Timermsg, 0);
if (error != 0)
{
DeleteExtIO ((IOREQUEST *) Timermsg);
return FALSE;
}
return TRUE;
}
/***************************************************************************
Function : hexit
Purpose : cleans up and exits
Entry :
Returns :
****************************************************************************/
void
hexit (int exit_val)
{
if (UtilityBase)
{
CloseLibrary (UtilityBase);
}
if (Timermsg != NULL)
{
DeleteTimer (Timermsg);
}
/*
* close log file if open
*/
if (fp)
fclose (fp);
exit (exit_val);
}
/***************************************************************************
Function : DeleteTimer
Purpose: Deletes Timer
Entry :
Returns :
****************************************************************************/
void
DeleteTimer (TIMERREQUEST * tr)
{
MSGPORT *tp;
tp = tr->tr_node.io_Message.mn_ReplyPort;
if (tr != 0)
{
CloseDevice ((IOREQUEST *) tr);
DeleteExtIO ((IOREQUEST *) tr);
}
if (tp != 0)
DeletePort (tp);
}
/***************************************************************************
Function : tv_diff
Purpose : returns difference in msecs between two TIMEVALS,
or -1 if overflow
Entry :
Returns :
****************************************************************************/
LONG
tv_diff (TIMEVAL * tv1, TIMEVAL * tv2)
{
LONG val;
val = (LONG) tv2->tv_secs - (LONG) tv1->tv_secs;
/*
* quick and nasty range check
*/
if (labs (val) > 4294966L)
return -1;
val *= 1000;
val += (((LONG) tv2->tv_micro) - ((LONG) tv1->tv_micro)) / 1000;
return val;
}
/***************************************************************************
Function : tv_diff_str
Purpose : returns difference in msecs between two TIMEVALS
expressed as secs.msecs string
Entry :
Returns :
****************************************************************************/
char *
tv_diff_str (TIMEVAL * tv1, TIMEVAL * tv2)
{
LONG val;
val = tv_diff (tv1, tv2);
return (format_diff_str (val, " (%s)"));
}
/***************************************************************************
Function : format_diff_str
Purpose : formats diff string
Entry :
Returns :
****************************************************************************/
char *
format_diff_str (LONG val, char *form)
{
static char mbuf[80];
char tmp[80];
tmp[0] = ' ';
if (val == -1)
{
return " ( >999.999 ) ";
}
if (val < 0)
{
tmp[0] = '-';
val = -val;
}
else if (val > 0)
{
tmp[0] = '+';
}
if (val > 999999)
{
return " ( >999.999 ) ";
}
sprintf (&tmp[1], " %3d.%03d", val / 1000, val % 1000);
sprintf (mbuf, form, tmp);
return mbuf;
}
/***************************************************************************
Function : set_system_time
Purpose: sets system date/time
Entry : TIMEVAL
Returns : void
****************************************************************************/
void
set_system_time (TIMEVAL * tv)
{
Timermsg->tr_node.io_Command = TR_SETSYSTIME;
Timermsg->tr_time.tv_secs = tv->tv_secs;
Timermsg->tr_time.tv_micro = tv->tv_micro;
if (DoIO ((IOREQUEST *) Timermsg))
{
fprintf (stderr, "set_system_time() - DoIO fail\n");
hexit (1);
}
}
/***************************************************************************
Function : get_system_time
Purpose: gets system date/time
Entry : ptr to TIMEVAL
Returns : void
****************************************************************************/
void
get_system_time (TIMEVAL * tv)
{
Timermsg->tr_node.io_Command = TR_GETSYSTIME;
if (DoIO ((IOREQUEST *) Timermsg))
{
fprintf (stderr, "get_time() - DoIO fail\n");
hexit (1);
}
tv->tv_secs = Timermsg->tr_time.tv_secs;
tv->tv_micro = Timermsg->tr_time.tv_micro;
}
/***************************************************************************
Function : get_battclock_time
Purpose: Get Battery Backed-up Clock time
Entry : ptr to TIMEVAL structure
Returns :
****************************************************************************/
void
get_battclock_time (TIMEVAL * tv)
{
tv->tv_secs = ReadBattClock ();
tv->tv_micro = 0;
}
/***************************************************************************
Function : set_battclock_time
Purpose: Set Battery Backed-up Clock time
Entry : ptr to TIMEVAL structure
Returns :
****************************************************************************/
void
set_battclock_time (TIMEVAL * tv)
{
WriteBattClock (tv->tv_secs);
}
/***************************************************************************
Function : tv_update
Purpose : updates a TIMEVAL with nnn msecs
Entry :
Returns :
****************************************************************************/
void
tv_update (TIMEVAL * tv, LONG msecs)
{
LONG t_secs, t_msecs;
TIMEVAL tv_tmp = *tv;
BOOL flag = TRUE;
if (msecs < 0)
{
flag = FALSE;
msecs = -msecs;
}
t_secs = msecs / 1000;
t_msecs = msecs % 1000;
/*
* conv microsecs field to msecs
*/
tv_tmp.tv_micro %= 1000;
if (flag == TRUE)
{
/* add */
tv_tmp.tv_micro += t_msecs;
if (tv_tmp.tv_micro >= 1000)
{
tv_tmp.tv_micro %= 1000;
tv_tmp.tv_secs += 1;
}
tv_tmp.tv_secs += t_secs;
}
else
{
/* subtract */
if (tv_tmp.tv_micro < t_msecs)
{
tv_tmp.tv_micro += 1000 - t_msecs;
tv_tmp.tv_secs -= 1;
}
tv_tmp.tv_secs -= t_secs;
}
/*
* conv msecs back to microsecs
*/
tv_tmp.tv_micro *= 1000;
/*
* update given TIMEVAL
*/
*tv = tv_tmp;
}
/***************************************************************************
Function : check4battclock
Purpose: Inits other stuff
Entry :
Returns :
****************************************************************************/
BOOL
check4battclock (void)
{
UtilityBase = (LIBRARY *) OpenLibrary ("diskfont.library", 0L);
if (UtilityBase == NULL)
{
fprintf (stderr, "Can't open diskfont.library\n");
return FALSE;
}
UtilityBase = (LIBRARY *) OpenLibrary ("utility.library", EARLIEST_LIB);
if (UtilityBase == NULL)
{
fprintf (stderr, "Abort: only runs under AmigaDOS 2.04 and above\n");
return FALSE;
}
/*
* see if Battery Clock there
*/
BattClockBase = OpenResource (BATTCLOCKNAME);
if (BattClockBase == NULL)
{
fprintf (stderr, "Abort: can't find a Battery Clock\n");
return FALSE;
}
return TRUE;
}
/***************************************************************************
Function : get_syncd_battclock_time
Purpose: reads battclock and returns when sec just ticked over
Entry :
Returns :
****************************************************************************/
void
get_syncd_battclock_time (TIMEVAL * tv)
{
TIMEVAL tv_tmp;
get_battclock_time (&tv_tmp);
do
{
get_battclock_time (tv);
}
while (tv_tmp.tv_secs == tv->tv_secs);
}
/***************************************************************************
Function : get_syncd_system_time
Purpose: reads sysclock and returns when sec just ticked over
Entry :
Returns :
****************************************************************************/
void
get_syncd_system_time (TIMEVAL * tv)
{
TIMEVAL tv_tmp;
get_system_time (&tv_tmp);
do
{
get_system_time (tv);
}
while (tv_tmp.tv_secs == tv->tv_secs);
}
/***************************************************************************
Function : print_clock
Purpose: prints clock time surrounded by given strings
Entry :
Returns :
****************************************************************************/
void
print_clock (char *pre, TIMEVAL * tv, char *post)
{
/*
* print results
*/
printf ("%s%s%s", pre, tv2str (tv), post);
fflush (stdout);
}
/***************************************************************************
Function : display both clocks
Purpose: as the name suggests
Entry :
Returns :
****************************************************************************/
void
display_clocks (TIMEVAL * tv_b, TIMEVAL * tv_s)
{
print_clock ("Battery clock time = ", tv_b, "\n");
print_clock ("System clock time = ", tv_s, tv_diff_str (tv_b, tv_s));
printf ("\n");
}
/***************************************************************************
Function : adjust a clock
Purpose: adjusts either system clock or battclock by given
number of millisecs
Entry :
Returns :
****************************************************************************/
void
adjust_clock (LONG msecs, TIMEVAL * tv)
{
static TIMEVAL tv_tmpx;
/*
* wait until given clock wraps over a second
*/
if (s_flag == TRUE)
{
get_syncd_system_time (&tv_sysclock);
tv_tmpx = tv_sysclock;
tv_update (&tv_tmpx, msecs);
set_system_time (&tv_tmpx);
}
else
{
LONG res;
/*
* battclock here
*/
get_syncd_battclock_time (&tv_battclock);
tv_tmpx = tv_battclock;
tv_update (&tv_tmpx, msecs);
res = 1000 - (tv_tmpx.tv_micro / 1000);
tv_update (&tv_battclock, 1000);
++tv_tmpx.tv_secs;
/*
* - wait a bit to account for fraction of a sec
*/
pause (res);
set_battclock_time (&tv_tmpx);
}
*tv = tv_tmpx;
}
/***************************************************************************
Function : print_old_new
Purpose: as the name suggests
Entry :
Returns :
***************************************************************************/
void
print_old_new (char *ptr, TIMEVAL * tv_old, TIMEVAL * tv_new)
{
printf ("Old %s clock time = ", ptr);
print_clock ("", tv_old, "\n");
printf ("New %s clock time = ", ptr);
print_clock ("", tv_new, tv_diff_str (tv_old, tv_new));
printf ("\n");
}
/***************************************************************************
Function : set_system_time_to_syncd_battclock
Purpose: sets system clock to battclock time when it ticks
over a second.
Entry :
Returns :
***************************************************************************/
LONG
set_system_time_to_syncd_battclock ()
{
get_syncd_battclock_time (&tv_battclock);
get_system_time (&tv_sysclock);
set_system_time (&tv_battclock);
return (tv_diff (&tv_battclock, &tv_sysclock));
}
/***************************************************************************
Function : set_battclock_time_to_syncd_system_time
Purpose: sets battery clock to system time when it ticks
over a second.
Entry :
Returns :
****************************************************************************/
LONG
set_battclock_time_to_syncd_system_time ()
{
TIMEVAL tv_tmp;
LONG diff;
/*
* we need to mess around a bit to get diff
* between batt and system clock because batt clock
* is only accurate to 1 sec
*/
get_syncd_battclock_time (&tv_battclock);
get_system_time (&tv_tmp);
diff = tv_diff (&tv_battclock, &tv_tmp);
get_syncd_system_time (&tv_sysclock);
set_battclock_time (&tv_sysclock);
/*
* now correct battclock time to give msecs precision
* PROVIDED that diff was in range (<999 secs) else ignore
* trying to be precise.
*/
if (diff != -1)
{
tv_battclock = tv_sysclock;
tv_update (&tv_battclock, diff);
}
return (-diff);
}
/***************************************************************************
Function : wait_for_timer
Purpose: Waits until given time expires
Entry :
Returns :
****************************************************************************/
void
wait_for_timer (TIMERREQUEST * tr, TIMEVAL * tv)
{
MSGPORT *tp;
ULONG flags;
tp = tr->tr_node.io_Message.mn_ReplyPort;
tr->tr_node.io_Command = TR_ADDREQUEST;
tr->tr_time.tv_secs = tv->tv_secs;
tr->tr_time.tv_micro = tv->tv_micro;
SendIO ((IOREQUEST *) tr);
flags = Wait ((1L << tp->mp_SigBit) | SIGBREAKF_CTRL_C);
if (flags & SIGBREAKF_CTRL_C)
{
AbortIO ((IOREQUEST *) tr);
WaitIO ((IOREQUEST *) tr);
hexit (1);
}
}
/***************************************************************************
Function : pause
Purpose : waits for given millisecs
( or until ^C hit )
Entry :
Returns :
****************************************************************************/
void
pause (int millisecs)
{
static TIMEVAL tv;
tv.tv_secs = millisecs / 1000;
tv.tv_micro = (millisecs % 1000) * 1000;
wait_for_timer (Timermsg, &tv);
}
/***************************************************************************
Function : scan_args
Purpose: scans and validates command line
Entry :
Returns :
****************************************************************************/
void
scan_args (int argc, char **argv)
{
char *ptr;
char arch;
char plusminus;
int a = 0;
int n = 0;
int b = 0;
int d = 0;
int s = 0;
int t = 0;
int l = 0;
int L = 0;
while (--argc)
{
ptr = *++argv;
plusminus = *ptr++;
/*
* now look for options
*/
if ((plusminus == '-') || (plusminus == '+'))
{
++opt_count;
arch = *ptr++;
switch (arch)
{
case 'a': /* adjust clock time */
if (a++)
{
fprintf (stderr, "too many -a options\n");
hexit (1);
}
a_flag = TRUE;
if (sscanf (ptr, "%d", &adjust) != 1)
{
fprintf (stderr, "bad -a option value\n");
hexit (1);
}
if (plusminus == '-')
adjust = -adjust;
break;
case 'b':
if (b++)
{
fprintf (stderr, "too many -b options\n");
hexit (1);
}
b_flag = TRUE;
break;
case 'd':
if (d++)
{
fprintf (stderr, "too many -d options\n");
hexit (1);
}
d_flag = TRUE;
date_ptr = ptr;
break;
case 't':
if (t++)
{
fprintf (stderr, "too many -t options\n");
hexit (1);
}
t_flag = TRUE;
time_ptr = ptr;
break;
case 's':
if (s++)
{
fprintf (stderr, "too many -s options\n");
hexit (1);
}
s_flag = TRUE;
break;
case 'h':
usage (""); /* help */
hexit (1);
case 'l':
if (l++)
{
fprintf (stderr, "too many -l options\n");
hexit (1);
}
l_flag = TRUE;
logfile = (*ptr) ? ptr : "LOG_CLOCKTOOL:";
if ((fp = fopen (logfile, "a")) == NULL)
{
fprintf (stderr, "Can't open %s\n", logfile);
hexit (1);
}
break;
case 'L':
if (L++)
{
fprintf (stderr, "too many -L options\n");
hexit (1);
}
L_flag = TRUE;
logfile = (*ptr) ? ptr : "LOG_CLOCKTOOL:";
if ((fp = fopen (logfile, "a")) == NULL)
{
fprintf (stderr, "Can't open %s\n", logfile);
hexit (1);
}
break;
case 'n': /* put str in log file entry */
if (n++)
{
fprintf (stderr, "too many -n options\n");
hexit (1);
}
n_flag = TRUE;
xstr = ptr;
break;
default:
usage ("unknown option"); /* bad option */
hexit (1);
}
}
else
{
usage ("not an option");
hexit (1);
}
}
if (opt_count == 0)
return;
/*
* now validate options
*/
if (b_flag && s_flag)
{
usage ("only one -b or -s option"); /* bad option */
hexit (1);
}
if ((b_flag == FALSE) && (s_flag == FALSE))
{
usage ("need -b or -s option"); /* bad option */
hexit (1);
}
if (d_flag || t_flag)
{
if (d_flag)
{
if (*date_ptr == '\0')
{
fprintf (stderr, "need a date string\n");
hexit (1);
}
}
if (t_flag)
{
if (*time_ptr == '\0')
{
fprintf (stderr, "need a time string\n");
hexit (1);
}
}
return;
}
if (l_flag && L_flag)
{
usage ("only one -l or -L option"); /* bad option */
hexit (1);
}
if ((opt_count > 2) && (a_flag == TRUE))
{
usage ("invalid options with -a option"); /* bad option */
hexit (1);
}
if ((opt_count > 2) && (n_flag == FALSE))
{
usage ("need a -n option"); /* bad option */
hexit (1);
}
}
/***************************************************************************
Function : usage
Purpose: prints invocation parameters
Entry :
Returns :
****************************************************************************/
void
usage (char *p)
{
static char *rats[] =
{
"Usage modes :-",
" 1) display both : clocktool",
" 2) set selected",
" from other : clocktool -[b | s]",
" 3) set date/time : clocktool -[b | s] -d<date> -t<time> ",
" 4) adjust : clocktool -[b | s] +|-a<n>",
" 5) log then reset : clocktool -[b | s] -l<file> [-n<str>]",
" 6) log only : clocktool -[b | s] -L<file> [-n<str>]",
"\nOptions:",
" -b : battery clock",
" -s : system clock",
" -d<str> : set selected clock's date to str (dd-MMM-yy)",
" -t<str> : set selected clock's time to str (hh:mm[:ss])",
" (can use either or both d/t options)",
"",
" +|-a<n> : change selected clock by + or - <n> millisecs",
"",
" -l<file> : log time of clock to <file> ; reset from other",
" (default file = LOG_CLOCKTOOL:)",
" -L<file> : log time of clock to <file> ; don't reset from other",
" (default file = LOG_CLOCKTOOL:)",
" -n<str> : append the <str> to log file entry, e.g. \"reboot\"",
NULL
};
int j = 0;
char *ptr;
if (*p)
fprintf (stderr, "Error: %s\n\n", p);
printf (
"%s: Displays/adjusts/sets times of battery clock and/or system clock\n\n",
"ClockTool");
printf (
"Version %s [%s : %s] written by gduncan@werple.net.au\n\n",
VERSION, __DATE__, __TIME__);
while (ptr = rats[j++])
printf ("%s\n", ptr);
}
/* */